package com.zhome.gateway.filter.pre;

import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.zhome.gateway.constants.Constants;
import com.zhome.gateway.dto.ZhomeRouteDto;
import com.zhome.gateway.enums.FilterEnum;
import com.zhome.gateway.enums.GateWayCodeEnum;
import com.zhome.gateway.filter.AbstractZhomeZuulFilter;
import com.zhome.gateway.locator.MySqlClientRouteLocator;
import com.zhome.gateway.util.Ids;
import com.zhome.gateway.util.XssUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
/**
 * 请求进入的第一个Filter.
 * 做一些前置准备工作，以后供续Filter使用
 * @author cuiyh9
 * @date 2020/5/9
 */
@Slf4j
public class RequestPreFilter extends AbstractZhomeZuulFilter {

    @Autowired
    private MySqlClientRouteLocator mySqlClientRouteLocator;

    @Override
    public String filterType() {
        return Constants.PRE_KEY;
    }

    @Override
    public int filterOrder() {
        return FilterEnum.RequestPreFilterEnum.getFilterOrder();
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        initRequestId(ctx);
        // 根据PATH获取路由信息
        ZhomeRouteDto zhomeRouteDto = getZhomeRouteDto(ctx);
        if (ObjectUtils.isEmpty(zhomeRouteDto)) {
            setSkipToPostTypeFilter(ctx);
            setFailResponse(GateWayCodeEnum.INNER_ERROR);
        } else {
            ctx.put(Constants.RequestContextKey.CTX_X_FULL_URL, buildLocationFullUrl(ctx, zhomeRouteDto));
            ctx.put(Constants.RequestContextKey.CTX_X_ROUTEINFO, zhomeRouteDto);
            ctx.set(Constants.RequestContextKey.CTX_X_IS_MOCK, isMock(zhomeRouteDto));
            ctx.set(Constants.RequestContextKey.CTX_X_SUCCESSOR_CAN_EXECUTE, true);
            ctx.set(Constants.RequestContextKey.CTX_X_SERVER_NAME, zhomeRouteDto.getServerName());
        }
        return null;
    }

    /**
     * 初始化请求id
     * @param ctx
     */
    private void initRequestId(RequestContext ctx) {
        HttpServletRequest request = ctx.getRequest();
        String requestId = request.getHeader(Constants.RequestHeader.X_REQUEST_ID);
        if (StringUtils.isEmpty(requestId)) {
            requestId = Ids.uuid();
        }
        ctx.set(Constants.RequestContextKey.CTX_X_REQUEST_ID, requestId);;
    }

    /**
     * 构建请求转化的URL地址
     * @param ctx
     * @param zhomeRouteDto
     * @return
     */
    private String buildLocationFullUrl(RequestContext ctx, ZhomeRouteDto zhomeRouteDto) {
        HttpServletRequest request = ctx.getRequest();
        String actionName = String.valueOf(ctx.get(FilterConstants.REQUEST_URI_KEY));
        String queryString = request.getQueryString();
        StringBuilder fullUrl = new StringBuilder();
        fullUrl.append(zhomeRouteDto.getDomain());
        fullUrl.append(actionName);
        if (!StringUtils.isEmpty(queryString)) {
            fullUrl.append("?");
            fullUrl.append(XssUtils.cleanXSSHtml(queryString));
        }
        return fullUrl.toString();
    }



    private ZhomeRouteDto getZhomeRouteDto(RequestContext ctx) {
        String serviceName = String.valueOf(ctx.get(FilterConstants.PROXY_KEY));
        ZhomeRouteDto zhomeRouteDto = mySqlClientRouteLocator.getZhomeRouteDto(serviceName);
        return zhomeRouteDto;
    }

    private boolean isMock(ZhomeRouteDto zhomeRouteDto) {
        return zhomeRouteDto.getMock() == 1;
    }

}
